/**
 * 
 */
package com.scaffold.commons.web;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.Parser;
import org.htmlparser.filters.TagNameFilter;
import org.htmlparser.nodes.TagNode;
import org.htmlparser.tags.ImageTag;
import org.htmlparser.tags.MetaTag;
import org.htmlparser.util.NodeIterator;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;

import com.scaffold.commons.file.FileIO;

/**
 * 缓存网站内容
 * @author wangjg
 *
 */
public class CacheSite {
	
	private FileIO fileIO;

	private String currentUrl;
	
	private String htmlContent;
	
	private String storeDir = "imgbackup";

	List<String> getAttributeList(String tag, String attribute) throws ParserException {
		Parser parser = new Parser(this.htmlContent);

		NodeFilter filter1 = new TagNameFilter("meta");
		NodeList nodeList = parser.extractAllNodesThatMatch(filter1);
		if(nodeList.size()>0){
			MetaTag mtNode = (MetaTag) nodeList.elementAt(0);
		}

		parser.reset();
		NodeFilter imgFilter = new TagNameFilter(tag);
		NodeList imgNodeList = parser.extractAllNodesThatMatch(imgFilter);
		for(int i=0;i<imgNodeList.size();i++){
			TagNode node = (TagNode)imgNodeList.remove(i);
			String src = node.getAttribute("src");
		}

		return null;
	}
	
	private List<String> imgList = new ArrayList<String>();
	
	public void store() throws Exception{
		List<String> urls = this.getImgUrls(true);
		for(String url:urls){
			if(url!=null){
				String filePath = storeDir + url2path(url, true);
				this.store(url, filePath);
				this.imgList.add(url);
			}
		}
	}
	
	private void store(String url, String filePath) throws IOException {
		HttpClient http = new DefaultHttpClient();
		HttpGet method = new HttpGet(url);
		HttpResponse response = http.execute(method);
		if(response.getStatusLine().getStatusCode()==200){
			HttpEntity entity = response.getEntity();
			InputStream in = entity.getContent();
			this.fileIO.save(filePath, in);
			in.close();
		}
	}

	private List<String> getImgUrls() throws Exception{
		List<String> list = new ArrayList<String>();
		Parser parser = new Parser(htmlContent);

		NodeFilter filter1 = new TagNameFilter("meta");
		NodeList nodeList = parser.extractAllNodesThatMatch(filter1);
		if(nodeList.size()>0){
			MetaTag mtNode = (MetaTag) nodeList.elementAt(0);
		}

		parser.reset();
		NodeFilter imgFilter = new TagNameFilter("img");
		NodeList imgNodeList = parser.extractAllNodesThatMatch(imgFilter);
		for(int i=0;i<imgNodeList.size();i++){
			TagNode node = (TagNode)imgNodeList.remove(i);
			String src = node.getAttribute("src");
			list.add(src);
		}
		
		return list;
	}
	
	private StringBuilder newHtml = new StringBuilder();

	private List<String> getImgUrls(boolean reSetSrc) throws Exception{
		List<String> srclist = new ArrayList<String>();
		Parser parser = new Parser(htmlContent);

		NodeFilter filter1 = new TagNameFilter("meta");
		NodeList nodeList = parser.extractAllNodesThatMatch(filter1);
		if(nodeList.size()>0){
			MetaTag mtNode = (MetaTag) nodeList.elementAt(0);
		}

		newHtml.delete(0, newHtml.length());

		parser.reset();		
		NodeIterator imgNodeList = parser.elements();
		for(;imgNodeList.hasMoreNodes();){
			Node node = imgNodeList.nextNode();
			this.xx(node, srclist, reSetSrc);
			newHtml.append(node.toHtml(true));
		}
		
		return srclist;
	}
	
	private void xx(Node node, List<String> srclist, boolean reSetSrc) throws URISyntaxException{
		if(node instanceof ImageTag){
			ImageTag imageTag = (ImageTag)node;
			String src = imageTag.getImageURL();
			if(reSetSrc){
				src = this.getFullUrl(src);
				imageTag.setImageURL(src);
				srclist.add(src);
			}
		}else if(node.getChildren()!=null){
			NodeList children = node.getChildren();
			for(int i=0;i<children.size();i++){
				Node node1 = children.elementAt(i);
				xx(node1, srclist, reSetSrc);
			}
		}
	}
	
	private String getFullUrl(String url) throws URISyntaxException{
		if(url==null || url.isEmpty()){
			return null;
		}
		if(url.length()>7 && (url.startsWith("http://")||url.startsWith("https://"))){
			return url;
		}
		boolean rootStart = url.startsWith("/");
		if(!url.startsWith("/")){
			url = '/'+url;
		}
		url = getUrlParent(rootStart) + url;
		return url;
	}
	
	private String getUrlParent(boolean host) throws URISyntaxException{
		String url = this.currentUrl;
		
		if(host){
			int pos = url.indexOf("//");
			pos = url.indexOf('/', pos+2);
			url = url.substring(0, pos);
			return url;
		}
		
		int pos1 = url.lastIndexOf('?');
		if(pos1!=-1){
			url = url.substring(0, pos1);
		}
		int pos = url.lastIndexOf('/');
		String str = url.substring(0, pos);
		return str;
	}
	
	public static String url2path(String url, boolean ignoreQuery) throws URISyntaxException{
		URI uri = new URI(url);
		StringBuilder sb = new StringBuilder();
		sb.append('/');
		sb.append(uri.getScheme());
		sb.append('/');
		sb.append(uri.getHost());
		sb.append('/');
		sb.append(uri.getPort()==-1?80:uri.getPort());
		sb.append(uri.getPath());
		if(!ignoreQuery && uri.getQuery()!=null && uri.getQuery().length()>0){
			sb.append('#');
			sb.append(uri.getQuery());
		}
		return sb.toString();
	}

	public void setCurrentUrl(String currentUrl) {
		this.currentUrl = currentUrl;
	}

	public void setHtmlContent(String htmlContent) {
		this.htmlContent = htmlContent;
	}

	public void setStoreDir(String storeDir) {
		this.storeDir = storeDir;
	}

	public void setFileIO(FileIO fileService) {
		this.fileIO = fileService;
	}

	public String getNewHtml() {
		return newHtml.toString();
	}

	public List<String> getImgList() {
		return imgList;
	}
}
